#include "thread_pool.h"

/**
    init_pthread_pool:初始化线程池
        互斥锁
        条件变量
        销毁标志
        任务队列
        线程数量
        线程ID存储空间
    @pool:线程池地址
    @thread_num:线程池初始线程数量
 */
bool init_pthread_pool(ThreadPool* pool, int thread_num)
{
    //1.初始化互斥锁、条件变量
    pthread_mutex_init(&pool->mutex, NULL);
    pthread_cond_init(&pool->cond, NULL);

    //2.销毁标志位设置为false
    pool->shutdown = false;

    //3.创建任务队列头指针
    pool->task_list = NULL;

    //4.任务数量设置为0
    pool->waiting_task = 0;

    //5.malloc申请线程ID的存储空间
    pool->pids = malloc(sizeof(pthread_t) * thread_num);

    //6.线程数量置为指定的数量
    pool->active_threads = thread_num;

    //7.创建指定数量的线程
    for (int i = 0;i < thread_num;i++)
    {
        int ret = pthread_create(&(pool->pids[i]), NULL, common_task, (void*)pool);
        if (ret != 0)
        {
            errno = ret;
            perror("pthread_create error");
            exit(1);
        }
    }
    return true;
}

/**
    common_task：线程处理函数
    每个线程创建后都执行此函数，阻塞等待具体的任务
    当有任务时，唤醒线程去处理任务
    @arg:线程池地址

 */
void* common_task(void* arg)
{
    //1.接收线程池参数
    ThreadPool* pool = (ThreadPool*)arg;

    while (1)
    {
        pthread_mutex_lock(&pool->mutex);//上锁

        //如果没有任务，线程池销毁标志位假，则销毁线程池标志位，休眠等待
        while (pool->waiting_task == 0 && pool->shutdown == 0)
        {
            pthread_cond_wait(&pool->cond, &pool->mutex);
        }

        while (pool->waiting_task == 0 && pool->shutdown == 1)
        {
            pthread_mutex_unlock(&pool->mutex);
            pthread_exit(NULL);
        }

        if (pool->task_list == NULL)
            continue;

        Task* task = pool->task_list;
        pool->task_list = pool->task_list->next;
        task->next = NULL;//断开与原来队列的联系
        pool->waiting_task--;//任务数量--

        //解锁
        pthread_mutex_unlock(&pool->mutex);

        task->func(task->arg);

        free(task);
    }
}

/**
    add_task:创建一个任务，添加到队尾
 */

bool add_task(ThreadPool* pool, void* (*task)(void*), void* arg)
{
    //1.创建一个任务结点
    Task* new_task = malloc(sizeof(Task));

    //2.初始化这个任务结点
    new_task->func = task;
    new_task->arg = arg;
    new_task->next = NULL;

    //2.上锁
    pthread_mutex_lock(&pool->mutex);

    //3.把任务添加到任务队列的末尾
    if (pool->task_list == NULL)//是队尾，直接加到队尾
    {
        pool->task_list = new_task;
    }
    else
    {
        Task* p = pool->task_list;
        while (p->next != NULL)
        {
            p = p->next;
        }
        p->next = new_task;//找到队尾
    }
    pool->waiting_task++;

    //解锁
    pthread_mutex_unlock(&pool->mutex);

    //唤醒休眠的线程处理任务
    pthread_cond_signal(&pool->cond);
}


//设置销毁标志为true，唤醒所有线程，等待所有线程结束
void threadpool_destroy(ThreadPool* pool)
{
    //销毁标志为真
    pool->shutdown = true;

    //唤醒所有休眠线程
    pthread_cond_broadcast(&pool->cond);

    //等待所有线程完成任务
    for (int i = 0;i < pool->active_threads;i++)
    {
        pthread_join(pool->pids[i], NULL);
    }

    //释放申请的资源
    free(pool->pids);
    free(pool);
}